#include <iostream>
#include <string>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/md5.h>
#include <fcntl.h>
#include <unistd.h>

using std::cout;
using std::endl;
using std::string;

string getPath(string path)
{
    string subPath = path.substr(0, path.find_last_of('/'));
    return subPath.substr(subPath.find_last_of('/') + 1);
}

static void getMd5Sum(const string &path, string &md5val)
{
    md5val.clear();

    int fd = open(path.c_str(), O_RDONLY);
    if (fd == -1)
    {
        // 处理文件打开失败
        return;
    }

    // 使用 EVP 接口
    EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
    const EVP_MD *md = EVP_md5(); // 获取 MD5 算法

    // 初始化上下文
    if (EVP_DigestInit_ex(mdctx, md, nullptr) != 1)
    {
        // 错误处理
        EVP_MD_CTX_free(mdctx);
        close(fd);
        return;
    }

    char buf[1024 * 16];
    ssize_t ret;
    while ((ret = ::read(fd, buf, sizeof(buf))) > 0)
    {
        if (EVP_DigestUpdate(mdctx, buf, ret) != 1)
        {
            // 错误处理
            EVP_MD_CTX_free(mdctx);
            close(fd);
            return;
        }
    }

    if (ret < 0)
    {
        // 处理读取错误
        EVP_MD_CTX_free(mdctx);
        close(fd);
        return;
    }

    unsigned char result[MD5_DIGEST_LENGTH];
    unsigned int len;
    if (EVP_DigestFinal_ex(mdctx, result, &len) != 1)
    {
        // 错误处理
        EVP_MD_CTX_free(mdctx);
        close(fd);
        return;
    }

    EVP_MD_CTX_free(mdctx);
    close(fd);

    char hex[33]; // MD5 32字符 + '\0'
    for (int i = 0; i < MD5_DIGEST_LENGTH; ++i)
    {
        sprintf(hex + i * 2, "%02x", result[i]);
    }
    hex[32] = '\0';
    md5val = string(hex);
}

int main(int args, char *argv[])
{
    // cout << getPath("/home/mada/wgl/asdfasdfasdf") << endl;
    string path = "/home/met/terminal_cloud_disk/mada/sdaf/fasdf";
    // cout << path.substr(0, path.find_first_of('/', strlen("/home/met/terminal_cloud_disk/"))) << endl;
    string tmp;
    cout << tmp.size() << endl;

    getMd5Sum("./test_path.cc", tmp);
    cout << "tmp: " << tmp << endl;
    return 0;
}